#include <cstring>

#include "gt_file.h"
#include "gt_line.h"
#include "gt_search_util.h"

// ok
static int match_blank_line(result_t *result, const char *output) {
  size_t line_length = strlen(output);
  if (line_length == 0) {
    result->entries = create_blank_line(result);
    return 1;
  }

  const char *match = apply_regex(output, "^(\\033\\[36m)(--)(\\033\\[m)$");
  if (!match)
    return 0;

  result->entries = create_blank_line(result);
  pcre_free_substring(match);

  return 1;
}

// ok
static int match_file(result_t *result, const char *output) {
  const char *match = apply_regex(output, "^([^\\033]+)$");
  if (!match)
    return 0;

  if (!validate_file(match))
    return 1;

  result->entries = create_file(result, (char *)match);
  pcre_free_substring(match);

  return 1;
}

// ok
static int match_line(result_t *result, const char *output) {
  const char *match = apply_regex(output, "^\\d+");
  if (!match)
    return 0;

  size_t line_number = atoi(match);
  pcre_free_substring(match);

  if (line_number == 0)
    return 0;

  match = apply_regex(output, "(?<=([-=]\\033\\[m)).*$");

  if (match) {
    result->entries =
        create_unselectable_line(result, (char *)match, line_number);
    pcre_free_substring(match);
    return 1;
  }

  range_t highlight = {0, 0};
  size_t line_length = 1024;
  char *line = (char *)calloc(line_length, sizeof(*line));

  match = apply_regex(output, "(?<=([:]\\033\\[m))[^\\033]*");
  if (!match)
    return 0;

  resize_string(&line, &line_length, strlen(match));
  strcat(line, match);
  pcre_free_substring(match);

  /* match the highlighted match */
  match = apply_regex(output, "(?<=(\\033\\[1;31m))[^\\033]*");
  if (!match)
    return 0;

  highlight.begin = strlen(line);
  highlight.end = highlight.begin + strlen(match);

  resize_string(&line, &line_length, strlen(match));
  strcat(line, match);
  pcre_free_substring(match);

  /* match rest of line */
  match = apply_regex(output, "(?<=(\\033\\[m))[^\\033]*$");
  if (!match)
    return 0;

  resize_string(&line, &line_length, strlen(match));
  strcat(line, match);
  pcre_free_substring(match);

  result->entries = create_line(result, line, line_number, highlight);

  return 1;
}

// ok
void do_git_search(search_t *search) {
  char default_args[] = "-n --heading --color=always ";
  external_parser_t git_grep = {default_args, match_file, match_line,
                                match_blank_line};

  popen_search(search, &git_grep);
}